/*  
  -- The Lime II Project -- 

  A tuplespaces-based middleware for coordinating agents and mobile hosts.
  Copyright (C) 2005.
  Gian Pietro Picco, Amy L. Murphy, Lorenzo Bellini.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received this copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
*/

package lime2;
import lights.interfaces.*;

/**
 * LimeTemplates are used for pattern matching in queries. LimeTemplates are passed as <i>input</i> to the methods 
 * of LimeTupleSpace. They are also required to instantiate new Reaction objects.
 * <br>
 * Please note that the public constructors of LimeTemplates perform parameter checking: null arguments are not 
 * accepted, although the null value for the TupleID field has the special meaning of "TupleID.UNSPECIFIED".
 * The null value for the TupleID field of a LimeWrapper (heir) is converted within the corresponding limified tuple 
 * into the formal TupleID.class (and vice-versa). 
 * <br>
 * The mechanism is <i>transparent</i> to users: there are two constructors for LimeTemplate; one allows to choose the
 * specific (non null) TupleID to match, the second automatically sets to null the TupleID field (meaning 
 * "TupleID.UNSPECIFIED"). 
 * <br>
 * The method "getTupleID()" is missing from class LimeTemplate because it could return null. On the contrary you can
 * invoke it on instances of LimeTuples since a LimeTuple always has <i>specific</i> TupleID.  
 * <br>  
 * Lime doesn't provide an explicit match-all value for TupleIDs because application programmers shouldn't be very
 * interested in manipulating TupleIDs (maybe they want to provide their own ID tag IField); nevertheless they can 
 * access the TupleID of "outed" tuples and use them in queries. 
 * <br>
 * So the semantics doesn't lack any power. 
 * <br> 
 * <br>
 * Examples of syntax and semantics: 
 * <P>
 * &#9679 matches all tuples 
 * <i><br>
 * new LimeTemplate(Location.UNSPECIFIED, Location.UNSPECIFIED, new Tuple())
 * </i><br><br>
 * &#9679 matches all tuples that are on host X 
 * <i><br>
 * new LimeTemplate(X, Location.UNSPECIFIED, new Tuple())
 * </i><br><br>
 * &#9679 matches all tuples whose destination is host Y
 * <i><br>
 * new LimeTemplate(Location.UNSPECIFIED, Y, new Tuple())
 * </i><br><br>
 * &#9679 matches all tuples on host X whose destination is host Y
 * <i><br>
 * new LimeTemplate(X, Y, new Tuple())
 * </i><br><br>
 * &#9679 matches ITuple pattern T 
 * <i><br>
 * new LimeTemplate(Location.UNSPECIFIED, Location.UNSPECIFIED, T);
 * </i><br><br>
 * &#9679 matches ITuple pattern T for tuples that are on host X
 * <i><br>
 * new LimeTemplate(X, Location.UNSPECIFIED, T)
 * </i><br><br>
 * &#9679 matches ITuple pattern T for tuples migrating to host Y
 * <i><br>
 * new LimeTemplate(Location.UNSPECIFIED, Y, T)
 * </i><br><br>
 * &#9679 matches tuples with TupleID ID
 * <i><br>
 * new LimeTemplate(ID, Location.UNSPECIFIED, Location.UNSPECIFIED, new Tuple());
 * </i><br><br>
 * &#9679 etc..
 *  
 * @author Gian Pietro Picco
 * @author Amy Murphy
 * @author Lorenzo Bellini
 */

public class LimeTemplate extends LimeWrapper 
{
 /**
  * Constructor method. Private.
  *
  * @param w LimeWrapper
  */	
 private LimeTemplate(LimeWrapper w)
 {
  super(w.id, w.cur, w.dest, w.tuple);	
 }
	
 /**
  * Constructor method. Allows to perform searches using specific values (TupleID included); performs parameter 
  * checking.
  * 
  * @param id the TupleID
  * @param cur the current Location
  * @param dest the destination Location
  * @param tuple the encapsulated tuple
  */
 public LimeTemplate(TupleID id, Location cur, Location dest, ITuple tuple) 
 {
  super();	
  
  // parameter checking
  //if (id == null || cur == null || dest == null || tuple == null) throw new IllegalArgumentException("null value");
  
  this.id = id;
  this.cur = cur;
  this.dest = dest;
  this.tuple = tuple;
 }

 /**
  * Constructor method. TupleID is set to "TupleID.UNSPECIFIED"; performs parameter checking. 
  * 
  * @param cur current Location
  * @param dest destination Location
  * @param tuple encapsulated tuple
  */
 public LimeTemplate(Location cur, Location dest, ITuple tuple)
 {
  super();
  
  // parameter checking
  if (cur == null || dest == null || tuple == null) throw new IllegalArgumentException("null value");
  
  this.id = null;
  this.cur = cur;
  this.dest = dest;
  this.tuple = tuple;
 }
 
 /**
  * Returns the current Location field of this LimeTemplate.
  * 
  * @return Location
  */
 public Location getCurrent() 
 { 
  return cur; 
 }

 /**
  * Returns the destination Location field of this LimeTemplate.
  * 
  * @return Location
  */
 public Location getDestination() 
 { 
  return dest; 
 }

 /**
  * Returns the wrapped ITuple of this LimeTemplate.
  * 
  * @return encapsulated ITuple
  */
 public ITuple getTuple() 
 { 
  return tuple; 
 }

 /**
  * Converts a LimeTemplate into a "limified" ITuple. 
  * In a limified tuple, aka flattened (or flat) tuple, the first field is the TupleID, second is the current 
  * Location, third is the destination Location and the remaining fields are the contents of the original tuple. 
  * The ITuple returned is a shallow copy of the ITuple contained in the LimeTemplate.
  * 
  * @return "limified" ITuple
  */ 
 ITuple limify() 
 {
  return this.limifyWrapper();	
 }

 /**
  * Converts a "limified" (flattened) ITuple into a LimeTemplate. If any of the fields are not of the proper type, 
  * (e.g., first field is TupleID, second is Location, and third is Location), <code>null</code> is returned. 
  * The ITuple within the returned LimeTemplate is a shallow copy of the tuple passed as a parameter.
  *
  * @param flat "limified" ITuple
  * @return corresponding LimeTemplate
  */ 
 static LimeTemplate delimify(ITuple flat) 
 {
  LimeWrapper w = delimifyWrapper(flat);
  if (w == null) return null; else return new LimeTemplate(w);	
 }

 /**
  * toString method.
  * 
  * @return concise textual representation of this LimeTuple
  */
 public String toString() 
 {
  return "[LimeTemplate]" + 
         " tid="  + (id == null ? "null" : id.toString()) + 
         " cur="  + (cur == null ? "null" : cur.toString()) + 
		 " dest=" + (dest == null ? "null" : dest.toString()) +
		 " tup="  + (tuple == null ? "null" : tuple.toString());
 }
 


}